#ifndef BINARIACPU_H
#define BINARIACPU_H

//Incluyo la clase Mersenne-Twister para la generación de números aleatorios en C++
#include "../utils/mt.h"

/****************** Representacion binaria ********************/

/******************* Declaracion de Funciones del Host *************************/
void representacionBinariaCPU(bool *poblacionActualHost, bool *nuevaPoblacionHost, float *fitnessActualHost, float *nuevoFitnessHost, int * poblacionActualAcambiar, int *  nuevaPoblacionAcambiar,bool * individuosAMigrarHostCPU, MersenneTwister* mt, int iteracion, int tamVectorPoblacion, int tamVectorFitness, bool *individuoAMigrarCPUaGPUhost, float* fitnessOrdenadoHostCPU, int* indicesFitnessOrdenadoHostCPU, float* probabilidadRuletaHostCPU, float* fitnessTotalParaRuletaHostCPU, unsigned long* numerosAleatoriosSeleccion, unsigned long* numerosAleatoriosCruzamiento, unsigned long* numerosAleatoriosMutacion, unsigned long* numerosAleatoriosProbabilidadCruzamiento, unsigned long* numerosAleatoriosProbabilidadMutacion, float* mejorFitnessIndividuoCPU, int tamVectorFitnessMejoresIndividuosCPU, bool* mejorIndividuoCPU, int tamVectorMejoresIndividuosCPU);

void imprimirBinariaCPU(float* fitnessHost, int tamVectorFitness, bool* poblacionHost, int tamVectorPoblacion, int iteracion);
int obtenerMejorIndividuoBinaria(int nroPoblacion, float* vectorFitness);
/******************* Declaracion de Funciones Global del  ********************/

void inicializarPoblacionBinariaCPU(bool* poblacion, float* fitnessActual, MersenneTwister *mt, int cantCromosomasPoblacion, float* fitnessOrdenadoHostCPU, unsigned long* numerosAleatoriosInicializacion);
void mainKernelBinariaCPU(bool* poblacionActual, bool* nuevaPoblacion, float* fitnessActual, float* nuevoFitness, int * poblacionActualAcambiar, int *  nuevaPoblacionAcambiar, bool* individuosAMigrar, MersenneTwister *mt, int nroPoblacion, int posActual, bool *individuoAMigrarCPUaGPUhost,  float* fitnessOrdenado, int* vectorIndicesFitnessOrdenado, int iteracion, float* probabilidadRuleta, float* fitnessTotalParaRuleta, unsigned long* numerosAleatoriosSeleccion, unsigned long* numerosAleatoriosCruzamiento, unsigned long* numerosAleatoriosMutacion, unsigned long* numerosAleatoriosProbabilidadCruzamiento, unsigned long* numerosAleatoriosProbabilidadMutacion, bool* mejorIndividuo, float* mejorFitnessIndividuoCPU);
void obtenerMejoresIndividuoBinariaCPU(bool* poblacion, float* fitness, bool* mejorIndividuo, float* mejorFitnessIndividuoCPU);
void imprimirMejorIndividuoBinariaCPU(float* mejorFitnessIndividuoCPU, int tamVectorFitnessMejoresIndividuosCPU, bool* mejorIndividuoCPU, int tamVectorMejoresIndividuosCPU, int iteracion);

void migracionRepresentacionBinariaCPU(bool* poblacionActual, float* fitnessActual, bool* individuosAMigrar, MersenneTwister *mt, bool* individuoAMigrarGPUaCPUhost);

/******************* Declaracion de Funciones internas del  *****************/

void individuosAMigrarRepresentacionBinariaCPU(float* nuevoFitness, bool* nuevaPoblacion, bool* individuosAMigrar, int nroPoblacion, int posActual, bool *individuoAMigrarCPUaGPUhost);

void asignarProbabilidadRuletaBinariaCPU(float* fitnessActual, float* probabilidadRuletaBinaria, float* fitnessTotalParaRuleta,  MersenneTwister *mt, int nroPoblacion, int posActual);

int seleccionBinariaCPU(float* vectorFitness, float* probabilidadRuleta, int* vectorIndicesFitnessOrdenado, MersenneTwister *mt, int ejecutarFuncion, int nroPoblacion, int posActual, unsigned long* numerosAleatoriosSeleccion, int nroIndividuo);
int seleccionPorTorneoBinariaCPU(float* vectorFitness, MersenneTwister *mt, int nroPoblacion, int posActual, unsigned long* numerosAleatoriosSeleccion, int nroIndividuo);
int seleccionPorRangoBinariaCPU(int* vectorIndicesFitnessOrdenado, MersenneTwister *mt, int nroPoblacion, int posActual, unsigned long* numerosAleatoriosSeleccion, int nroIndividuo);
int seleccionRuedaRuletaBinariaCPU(float* probabilidadRuleta, MersenneTwister *mt, int nroPoblacion, int posActual, unsigned long* numerosAleatoriosSeleccion, int nroIndividuo);

void cruzamientoRepresentacionBinariaCPU(bool* poblacionActual, bool* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, float probabilidad, MersenneTwister *mt, int ejecutarFuncion, int nroPoblacion, int posActual, unsigned long* numerosAleatoriosProbabilidadCruzamiento, unsigned long* numerosAleatoriosCruzamiento);
void cruzamientoCromosoma1PuntoBinariaCPU(bool* poblacionActual, bool* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, float probabilidad, MersenneTwister *mt, int nroPoblacion, int posActual, unsigned long* numerosAleatoriosProbabilidadCruzamiento, unsigned long* numerosAleatoriosCruzamiento);
void cruzamientoCromosoma2PuntosBinariaCPU(bool* poblacionActual, bool* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, float probabilidad, MersenneTwister *mt, int nroPoblacion, int posActual, unsigned long* numerosAleatoriosProbabilidadCruzamiento, unsigned long* numerosAleatoriosCruzamiento);
void cruzamientoCromosomaUniformeBinariaCPU(bool* poblacionActual, bool* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, float probabilidad, MersenneTwister *mt, int nroPoblacion, int posActual, unsigned long* numerosAleatoriosProbabilidadCruzamiento);

void mutacionBinariaCPU(bool* poblacion, float probabilidad, MersenneTwister *mt, int ejecutarFuncion, int nroPoblacion, int posActual, unsigned long* numerosAleatoriosProbabilidadMutacion, unsigned long* numerosAleatoriosMutacion);
void mutacionPorInversion(bool* poblacion, float probabilidad, MersenneTwister *mt, int nroPoblacion, int posActual, unsigned long* numerosAleatoriosProbabilidadMutacion, unsigned long* numerosAleatoriosMutacion);

void asignarFitnessBinariaCPU(bool* nuevaPoblacion, float* nuevoVectorFitness, int nroPoblacion, int posActual, float* fitnessOrdenado);

void reemplazoBinariaCPU(bool* poblacionActual, bool* nuevaPoblacion, int* poblacionActualAcambiar, int* nuevaPoblacionAcambiar, float * fitnessActual, float* nuevoFitness, int ejecutarFuncion, int nroPoblacion, int posActual);
void reemplazoElitistaBinariaCPU(bool* poblacionActual, bool* nuevaPoblacion, int* poblacionActualAcambiar, int* nuevaPoblacionAcambiar, float * fitnessActual, float* nuevoFitness, int nroPoblacion, int posActual);



#endif
